#ifndef __RENDER_STATES_H__
#define __RENDER_STATES_H__

#pragma once

#include "GraphicsCompileConfig.h"

namespace Nezha
{

	enum RS_CmpMode
	{
		RSCM_NEVER,
		RSCM_LESS,
		RSCM_EQUAL,
		RSCM_LESSEQUAL,
		RSCM_GREATER,
		RSCM_NOTEQUAL,
		RSCM_GREATEREQUAL,
		RSCM_ALWAYS,

		RSCM_NUM		
	};

	enum BlendFactor
	{
		BF_ONE,
		BF_ZERO,
		BF_DST_COLOR,
		BF_SRC_COLOR,
		BF_ONE_MINUS_DST_COLOR,
		BF_ONE_MINUS_SRC_COLOR,
		BF_DST_ALPHA,
		BF_SRC_ALPHA,
		BF_ONE_MINUS_DST_ALPHA,
		BF_ONE_MINUS_SRC_ALPHA,

		BF_NUM
	};

	enum BlendOperation
	{
		BO_ADD,
		BO_SUB,
		BO_REVERSE_SUB,
		BO_MIN,
		BO_MAX,

		BO_NUM
	};

	enum RS_CullOrder
	{
		RSCO_CCW,
		RSCO_CW,
		RSCO_NONE
	};

	enum RS_FillMode
	{
		RSFM_POINT,
		RSFM_WIREFRAME,
		RSFM_SOLID
	};

	enum RS_StencilOP
	{
		RSSOP_KEEP,
		RSSOP_ZERO,
		RSSOP_REPLACE,
		RSSOP_INCREMENT,					// clamping to 0
		RSSOP_DECREMENT,					// clamping to max
		RSSOP_INCREMENT_WRAP,			// wrapping back to 0
		RSSOP_DECREMENT_WRAP,
		RSSOP_INVERT,

		RSSOP_NUM
	};

	// blending
	struct RS_Blending
	{
		bool mBlendingEnable;
		BlendFactor mSrc;
		BlendFactor mDst;
		BlendOperation mOp;			// operation between src and dst.

		bool mSeparateBlending;
		BlendFactor mSrcAlpha;
		BlendFactor mDstAlpha;
		BlendOperation mAlphaOp;

		// alpha test
		RS_CmpMode mCmpMode;
		float mReference;

		RGBA mConstantColor;

		RS_Blending()
			:mBlendingEnable(false),
			mSrc(BF_SRC_ALPHA),
			mDst(BF_ONE_MINUS_SRC_ALPHA),
			mOp(BO_ADD),
			mSeparateBlending(false),
			mSrcAlpha(BF_ZERO),
			mDstAlpha(BF_ZERO),
			mAlphaOp(BO_ADD),
			mCmpMode(RSCM_ALWAYS),
			mReference(0),
			mConstantColor(0, 0, 0, 0)
		{

		}
	};

	// depth state
	struct RS_Depth
	{
		bool mEnabled;
		bool mWritable;
		RS_CmpMode mCmpMode;

		RS_Depth()
			:mEnabled(true),
			mWritable(true),
			mCmpMode(RSCM_LESSEQUAL)
		{

		}
	};

	// polygon offset
	struct RS_PolygonOffset
	{
		bool mFillEnabled;		// fill mode
		bool mLineEnabled;		// line mode
		bool mPointEnabled;	// point mode
		float mScale;
		float mBias;

		RS_PolygonOffset()
			:mFillEnabled(false),
			mLineEnabled(false),
			mPointEnabled(false),
			mScale(0.0f),
			mBias(0.0f)
		{
		}
	};

	// stencil state
	struct RS_Stencil
	{
		bool mEnabled;
		bool mTwoSide;
		RS_CmpMode mCmpMode;
		u32 mReference;
		u32 mMask;					// default : ~0
		u32 mWriteMask;			// default : ~0
		RS_StencilOP mOnFail;     // default : KEEP
		RS_StencilOP mOnZFail;    // default : KEEP	(stencil pass z fail)
		RS_StencilOP mOnPass;    // default : KEEP  (stencil & z pass)

		RS_Stencil()
			:mEnabled(false),
			mTwoSide(false),
			mCmpMode(RSCM_NEVER),
			mReference(0),
			mMask(0xFFFFFFFF),
			mWriteMask(0xFFFFFFFF),
			mOnFail(RSSOP_KEEP),
			mOnZFail(RSSOP_KEEP),
			mOnPass(RSSOP_KEEP)
		{

		}
	};

	// color mask
	struct RS_ColorMask
	{
		u8 mRed;
		u8 mGreen;
		u8 mBlue;
		u8 mAlpha;

		RS_ColorMask()
			:mRed(1)
			,mGreen(1)
			,mBlue(1)
			,mAlpha(1)
		{
		}
	};

}//end namespace Nezha

#endif //end __RENDER_STATES_H__